using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace HardMock.Domain
{
    class MethodCallExpression<T> : MethodCall
    {
        public MethodCallExpression(Expression<T> expression)
            : base(GetMethodInfo(expression), GetArguments(expression))
        {
        }

        private static IEnumerable<Argument> GetArguments(Expression<T> expression)
        {
            var methodCallExpression = (MethodCallExpression)expression.Body;
            return GetLambdaArguments(methodCallExpression).Select(ToArgument);
        }

        private static IEnumerable<LambdaExpression> GetLambdaArguments(MethodCallExpression methodCallExpression)
        {
            return methodCallExpression.Arguments.Select(a => Expression.Lambda(a)).ToList();
        }

        private static Argument ToArgument(LambdaExpression a)
        {
            var value = a.Compile().DynamicInvoke();

            return new Argument(value.GetType(), value);
        }


        private static MethodInfo GetMethodInfo(Expression<T> expression)
        {
            return ((MethodCallExpression)expression.Body).Method;
        }
    }
}